package org.hikari.qqbot.xiuxian.task.impl;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
import org.hikari.qqbot.xiuxian.command.ICommand;
import org.hikari.qqbot.xiuxian.command.standard.xunbao.DiYuXunBaoCommand;
import org.hikari.qqbot.xiuxian.command.standard.xunbao.TiQianLingQuDiYuXunBaoJiangLiCommand;
import org.hikari.qqbot.xiuxian.command.standard.xunbao.YiJianShengJiDongFuCommand;
import org.hikari.qqbot.xiuxian.service.bo.UserSetting;
import org.hikari.qqbot.xiuxian.task.TypedITask;
import org.hikari.qqbot.xiuxian.task.UserTaskRuntime;
import org.hikari.qqbot.xiuxian.util.BizUtil;
import org.hikari.qqbot.xiuxian.util.MessageUtil;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * created at 2024-12-25 17:46:00
 *
 * @author yinchao
 * @version 1.0
 **/
@Slf4j
@Component
public class XunBaoTask extends TypedITask<XunBaoTask.Config> {

    private volatile BaoZangInfo baoZang;

    @Override
    public String getId() {
        return "地狱寻宝";
    }

    @Override
    public ICommand initCommand(UserSetting setting) {
        Config config = config(setting);
        Date date = todayXunBaoTime(config);
        ICommand command = buildTiQianLingQuDiYuXunBaoJiangLiCommand().delay(date);
        return command.delay(date);
    }

    @Override
    public Collection<ICommand> process(UserTaskRuntime runtime, String message) {
        UserSetting setting = runtime.getUserSetting();
        Config config = config(setting);

        if (message.contains("你今日已领过寻宝府石了")) {
            Date date = tomorrowXunBaoTime(config);
            ICommand command = buildTiQianLingQuDiYuXunBaoJiangLiCommand().delay(date);
            return List.of(command);
        }

        if (message.contains("你还未获得寻宝府石")) {
            ICommand command = buildXunBaoCommand(config, 1);
            if (command == null) {
                return null;
            }
            Date date = todayXunBaoTime(config);
            return List.of(command.delay(date));
        }

        if (message.contains("地狱共分") && message.contains("每一层有三次寻宝的机会")) {
            ICommand command = buildXunBaoCommand(config, 1);
            if (command == null) {
                return null;
            }
            return List.of(command);
        }

        if (message.contains("寻宝位置")) {
            String part = MessageUtil.matchFirstPattern(message, "([0-9]+)层已寻完，(自动进入下一层|府石\\+[0-9]+)", 1);
            if (part != null) {
                int lvl = Integer.parseInt(part);
                if (lvl == config.getMaxLevel()) {
                    Date date = tomorrowXunBaoTime(config);
                    ICommand command = buildTiQianLingQuDiYuXunBaoJiangLiCommand().delay(date);
                    ICommand shengJiDongFuCommand = new YiJianShengJiDongFuCommand();
                    return List.of(shengJiDongFuCommand, command);
                }
                ICommand command = buildXunBaoCommand(config, lvl + 1);
                if (command == null) {
                    return null;
                }
                return List.of(command);
            }
        }

        return null;
    }

    private static ICommand buildTiQianLingQuDiYuXunBaoJiangLiCommand() {
        return new TiQianLingQuDiYuXunBaoJiangLiCommand();
    }

    private static Date tomorrowXunBaoTime(Config config) {
        return BizUtil.beginOfTomorrow().offset(DateField.HOUR, config.getXunBaoTime());
    }

    private static Date todayXunBaoTime(Config config) {
        return BizUtil.beginOfToday().offset(DateField.HOUR, config.getXunBaoTime());
    }

    private ICommand buildXunBaoCommand(Config config, int lvl) {
        BaoZangInfo bz = getOrRefreshBaoZang(config, new Date());
        if (bz == null) {
            return null;
        }
        Map<String, BaoZangLevelInfo> levels = bz.getData();
        BaoZangLevelInfo level = levels.get(String.valueOf(lvl));
        if (level == null) {
            log.info("无法获取到第{}层的宝藏信息", lvl);
            return null;
        }

        boolean challengeBoss = config.getFightMaxLevel() >= lvl;
        if (challengeBoss) {
            return new DiYuXunBaoCommand(level.getBoss(), level.getBz().get(0), level.getBz().get(1));
        } else {
            return new DiYuXunBaoCommand(level.getBz().get(0), level.getBz().get(1), level.getBz().get(2));
        }
    }

    private String formatBaoZangDate(Date date) {
        return DateUtil.format(date, "yyyyMMdd");
    }

    public BaoZangInfo getOrRefreshBaoZang(Config config, Date date) {
        String today = formatBaoZangDate(date);
        if (baoZang == null || !Objects.equals(today, baoZang.getDate())) {
            synchronized (this) {
                if (baoZang == null || !Objects.equals(today, baoZang.getDate())) {
                    BaoZangInfo newBaoZang = loadBaoZangInfo(config, date);
                    if (newBaoZang == null) {
                        return null;
                    }
                    if (!Objects.equals(today, newBaoZang.getDate())) {
                        log.info("没有找到{}的地域寻宝信息, 获取到的寻宝日期: {}", today, newBaoZang.getDate());
                        return null;
                    }
                    this.baoZang = newBaoZang;
                }
            }
        }
        return this.baoZang;
    }

    private BaoZangInfo loadBaoZangInfo(Config config, Date date) {
        String url = config.getUrl() + "?base=xbhz" + DateUtil.format(date, "yyyyMMdd");
        try (HttpResponse response = HttpUtil.createGet(url).execute()) {
            String bodyStr = response.body();
            log.info("请求寻宝地址: {} 返回数据: {}", url, bodyStr);
            if (bodyStr == null) {
                return null;
            }
            BaoZangInfo resp = JSONUtil.toBean(bodyStr, BaoZangInfo.class);
            if (resp == null) {
                log.info("无法解析寻宝返回数据结构");
                return null;
            }
            return resp;
        }
    }

    @Getter
    @Setter
    @ToString
    public static class Config {

        /**
         * 寻宝地址
         */
        private String url = "https://xb.qiihao.com:8443/kv";
        /**
         * 寻宝战斗的层数上限
         */
        private int fightMaxLevel = 20;
        /**
         * 寻宝最大层数
         */
        private int maxLevel = 20;
        /**
         * 每日的几点进行寻宝
         */
        private int xunBaoTime = 8;

    }

    @Getter
    @Setter
    public static class BaoZangInfo {

        private int code;
        private String date;
        private Map<String, BaoZangLevelInfo> data;

    }

    /**
     * {
     * "boss": "1-5",
     * "bz": [
     * "5-5",
     * "5-3",
     * "5-2"
     * ]
     * }
     */
    @Getter
    @Setter
    @ToString
    public static class BaoZangLevelInfo {

        /**
         * boss位置
         */
        private String boss;
        /**
         * 宝藏位置
         */
        private List<String> bz;

    }

}
